package com.rfid.transport;

public class RingBuffer {
    public static final int ERR_NONE = 0;
    public static final int ERR_SIZE_NOT_ENOUGH = 1;
    public static final int ERR_PUSH_LEN_TOO_SMALL = 2;
    public static final int ERR_BUFFER_IS_NULL = 3;
    public static final int ERR_PUSH_TOO_LARGE = 4;
    public static final int OPER_OK = 1;
    public static final int OPER_FAIL = 0;

    public RingBuffer(int size) {
        this.m_pBuffer = null;
        this.dwFont = 0;
        this.dwBack = 0;
        this.dwCursor = 0;
        this.m_size = 0;
        this.m_errCode = 0;
        this.m_pBuffer = new byte[size];
        this.m_size = size;
        this.dwFont = 0;
        this.dwBack = 0;
    }

    public static final int RB_NULL = -1;
    private byte[] m_pBuffer;
    private int dwFont;
    private int dwBack;
    private int dwCursor;
    private int m_size;
    private int m_errCode;

    public void Init() {
        if (this.m_pBuffer == null) return;
        this.dwFont = 0;
        this.dwBack = 0;
        this.dwCursor = 0;
        this.m_errCode = 0;
    }

    public int PushData(byte[] datBuf, int datLen) {
        if (this.m_pBuffer == null) {
            this.m_errCode = 3;
            return 0;
        }
        int usedSize = Offset(this.dwBack, this.dwFont);
        if (datLen > this.m_size - usedSize - 1) {
            this.m_errCode = 4;
            return 0;
        }
        int tmppos = Seek(this.dwFont, datLen);
        if (tmppos < this.dwFont && tmppos > 0) {
            System.arraycopy(datBuf, 0, this.m_pBuffer, this.dwFont, datLen - tmppos);
            System.arraycopy(datBuf, datLen - tmppos, this.m_pBuffer, 0, tmppos);
        } else System.arraycopy(datBuf, 0, this.m_pBuffer, this.dwFont, datLen);
        this.dwFont = tmppos;
        return 1;
    }

    public int Offset(int start, int end) {
        int offset = end - start;
        if (offset < 0) offset = this.m_size + offset;
        return offset;
    }

    public int Seek(int start, int offset) {
        if (start > this.m_size - 1 || start < 0) return -1;
        int newpos = start + offset;
        if (newpos > this.m_size - 1) newpos -= this.m_size;
        if (newpos < 0) newpos = this.m_size - 1 + newpos + 1;
        return newpos;
    }

    private boolean IsValidPos(int ipos) {
        if (this.dwBack == this.dwFont) return false;
        if (this.dwFont > this.dwBack) if (ipos < this.dwBack || ipos >= this.dwFont) return false;
        else if (ipos >= this.dwFont && ipos < this.dwBack) return false;
        return true;
    }

    public int GetLength(int startpos, int endpos) {
        if (startpos == -1) startpos = this.dwBack;
        if (endpos == -1) endpos = this.dwFont;
        if (!IsValidPos(startpos)) return 0;
        if (endpos != this.dwFont && !IsValidPos(endpos)) return 0;
        return Offset(startpos, endpos);
    }

    public boolean GetBufData(int dwStart, int offset, int dwLen, byte[] byDatBuf) {
        int tmppos = Seek(dwStart, offset);
        if (!IsValidPos(tmppos)) return false;
        int nlen = GetLength(tmppos, -1);
        if (dwLen < nlen) nlen = dwLen;
        if (tmppos + nlen > this.m_size) {
            int i = this.m_size - tmppos;
            System.arraycopy(this.m_pBuffer, tmppos, byDatBuf, 0, i);
            int j = Seek(tmppos, nlen);
            System.arraycopy(this.m_pBuffer, 0, byDatBuf, i, j);
        } else System.arraycopy(this.m_pBuffer, tmppos, byDatBuf, 0, nlen);
        return true;
    }

    public boolean GetBufData(int dwStart, int dwLen, byte[] byDatBuf) {
        return GetBufData(dwStart, 0, dwLen, byDatBuf);
    }

    public int PopData(byte[] datBuf, int popLen, Integer poped) {
        int usedSize = Offset(this.dwBack, this.dwFont);
        if (popLen > usedSize) popLen = usedSize;
        if (datBuf != null) GetBufData(this.dwBack, popLen, datBuf);
        if (poped != null) NdkSupport.SetIntegerValue(poped, popLen);
        this.dwBack = Seek(this.dwBack, popLen);
        return 1;
    }

    public int GetUsedSize() {
        return Offset(this.dwBack, this.dwFont);
    }

    public int SearchByte(int startpos, byte by) {
        int result = -1;
        byte[] ele = new byte[1];
        int next = 0;
        if (startpos == -1) startpos = this.dwBack;
        if (!IsValidPos(startpos)) return -1;
        next = startpos;
        while (next != -1) {
            ele[0] = 0;
            if (!GetBufData(next, 1, ele)) break;
            if (ele[0] == by) {
                result = next;
                break;
            }
            next = GetNewPos(next, 1);
        }
        return result;
    }

    public int GetNewPos(int start, int offset) {
        if (start == -1) start = this.dwBack;
        int endpos = Seek(start, offset);
        if (!IsValidPos(start) || !IsValidPos(endpos)) return -1;
        return endpos;
    }

    public int SearchWord(int startpos, char wd) {
        int result = -1;
        int next = 0;
        byte[] val = new byte[2];
        char cmpval = Character.MIN_VALUE;
        if (startpos == -1) startpos = this.dwBack;
        if (!IsValidPos(startpos)) return -1;
        next = startpos;
        while (next != -1) {
            if (!GetBufData(next, 2, val)) break;
            cmpval = (char) (val[0] & 0xFF | val[1] << 8 & 0xFF00);
            if (cmpval == wd) {
                result = next;
                break;
            }
            next = GetNewPos(next, 1);
        }
        return result;
    }

    public int GoNext(int start) {
        if (Offset(this.dwBack, start) >= Offset(this.dwBack, this.dwFont)) return -1;
        int inext = Seek(start, 1);
        if (Offset(this.dwBack, inext) >= Offset(this.dwBack, this.dwFont)) return -1;
        return inext;
    }

    public int GetLastErrorCode() {
        return this.m_errCode;
    }

    public int Cursor_MoveFist() {
        this.dwCursor = this.dwBack;
        if (Offset(this.dwBack, this.dwFont) == 0) return 0;
        return 1;
    }

    public int Cursor_MoveNext() {
        int tmp = Seek(this.dwCursor, 1);
        if (Offset(tmp, this.dwFont) == 0) return 0;
        this.dwCursor = tmp;
        return 1;
    }

    private int Cursor_GetOffset() {
        return Offset(this.dwCursor, this.dwFont);
    }

    public int Cursor_MoveBy(int len) {
        if (Cursor_GetOffset() - 1 < len) return 0;
        int tmp = Seek(this.dwCursor, len);
        this.dwCursor = tmp;
        return 1;
    }

    public int Cursor_GetMoved() {
        return Offset(this.dwBack, this.dwCursor);
    }

    public int Cursor_MoveBackBy(int len) {
        if (Cursor_GetMoved() < len) return 0;
        int tmp = Seek(this.dwCursor, -len);
        this.dwCursor = tmp;
        return 1;
    }

    public int Cursor_MoveTo(int newpos) {
        if (Offset(this.dwBack, newpos) >= Offset(this.dwBack, this.dwFont)) return 0;
        this.dwCursor = newpos;
        return 0;
    }
}
